package tetris.view;

import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
import com.sun.opengl.util.*;
import javax.swing.JPanel;
import tetris.model.blokken.Bord;

/**
 * JOGLGearsDemo.java <BR>
 * author: Brian Paul (converted to Java by Ron Cemer and Sven Goethel) <P>
 *
 * This version is equal to Brian Paul's version 1.2 1999/10/21
 */
public class BordPaneel3D extends JPanel implements GLEventListener, MouseListener, MouseMotionListener, KeyListener {

    public static void main(String[] args) {
        Frame frame = new Frame("Gear Demo");
        GLCanvas canvas = new GLCanvas();
        BordPaneel3D bordpaneel = new BordPaneel3D();
        canvas.addGLEventListener(bordpaneel);
        canvas.addKeyListener(bordpaneel);
        frame.add(canvas);
        frame.setSize(600, 600);
        final Animator animator = new Animator(canvas);
        frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                // Run this on another thread than the AWT event queue to
                // make sure the call to Animator.stop() completes before
                // exiting
                new Thread(new Runnable() {

                    public void run() {
                        animator.stop();
                        System.exit(0);
                    }
                }).start();
            }
        });
        frame.show();
        animator.start();

    }
    
    
    private float view_rotx = 200.0f,  view_roty = 20.0f,  view_rotz = 0.0f;
    private int raster;
    private int prevMouseX,  prevMouseY;
    private boolean mouseRButtonDown = false;
    private Bord bord;
    private int x = 7;
    private int y = 15;
    private int z = 7;
    private float scaleFactor = 2;
    private float distance = 25.0f;

    public void init(GLAutoDrawable drawable) {

        bord = new Bord(x, y, z);
        GL gl = drawable.getGL();
        GLUT glut = new GLUT();

        System.err.println("INIT GL IS: " + gl.getClass().getName());

        System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());

        gl.setSwapInterval(1);

        float pos[] = {5.0f, 5.0f, 10.0f, 0.0f};
        float red[] = {0.8f, 0.1f, 0.0f, 1.0f};
        float green[] = {0.0f, 0.8f, 0.2f, 1.0f};
        float blue[] = {0.2f, 0.2f, 1.0f, 1.0f};


        float ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
        float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
        float specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
        float position[] = {0.0f, 3.0f, 2.0f, 0.0f};
        float lmodel_ambient[] = {0.4f, 0.4f, 0.4f, 1.0f};
        float local_view[] = {0.0f};

        gl.glEnable(GL.GL_DEPTH_TEST);

        gl.glDepthFunc(GL.GL_LESS);

        gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0);
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0);
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);
        gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient, 0);
        gl.glLightModelfv(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, local_view, 0);

        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_LIGHT0);
        gl.glClearColor(0.0f, 0.1f, 0.1f, 0.0f);



        /*Teken het Raster*/
        raster = gl.glGenLists(1);
        gl.glNewList(raster, GL.GL_COMPILE);
        for (int i = 0; i <= x; i++) {
            for (int j = 0; j <= y; j++) {
                for (int k = 0; k <= z; k++) {
                    gl.glLineWidth (0.1f);
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0);
                    gl.glBegin(GL.GL_LINES);
                    gl.glVertex3f(i / scaleFactor, 0 / scaleFactor, k / scaleFactor);
                    gl.glVertex3f(i / scaleFactor, y / scaleFactor, k / scaleFactor);
                    gl.glEnd();
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0);
                    gl.glBegin(GL.GL_LINES);
                    gl.glVertex3f(i / scaleFactor, j / scaleFactor, 0 / scaleFactor);
                    gl.glVertex3f(i / scaleFactor, j / scaleFactor, z / scaleFactor);
                    gl.glEnd();
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0);
                    gl.glBegin(GL.GL_LINES);
                    gl.glVertex3f(0 / scaleFactor, j / scaleFactor, k / scaleFactor);
                    gl.glVertex3f(x / scaleFactor, j / scaleFactor, k / scaleFactor);
                    gl.glEnd();
                }
            }
        }
        gl.glEndList();


        gl.glEnable(GL.GL_NORMALIZE);

        drawable.addMouseListener(this);
        drawable.addMouseMotionListener(this);
    }

    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        GL gl = drawable.getGL();

        float h = (float) height / (float) width;

        gl.glMatrixMode(GL.GL_PROJECTION);


        gl.glLoadIdentity();
        gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -distance);
    }

    public void display(GLAutoDrawable drawable) {

        GL gl = drawable.getGL();
        GLUT glut = new GLUT();

        if ((drawable instanceof GLJPanel) &&
                !((GLJPanel) drawable).isOpaque() &&
                ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
            gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
        } else {
            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        }
        
        gl.glPushMatrix();

        /*Zet de camera viewport*/
        gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
        gl.glTranslatef(-(x / scaleFactor) / 2, -(y / scaleFactor) / 2, -(z / scaleFactor) / 2);

        gl.glEnable(GL.GL_BLEND);
        gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
        /*Teken het raster*/
        gl.glPushMatrix();
        gl.glCallList(raster);
        gl.glPopMatrix();
        gl.glDisable(GL.GL_BLEND);

        /*Teken de blokjes*/
        for (int i = 0; i < x; i++) {
            for (int j = 0; j < y; j++) {
                for (int k = 0; k < z; k++) {
                    if (bord.getBord()[i][j][k].isBezet()) {
                        gl.glPushMatrix();
                        gl.glTranslatef((i + 0.5f) / scaleFactor, (j + 0.5f) / scaleFactor, (k+0.5f) / scaleFactor);

                        float kleur[] = {bord.getBord()[i][j][k].getBlok().getKleur().getRed(),
                                bord.getBord()[i][j][k].getBlok().getKleur().getGreen(),
                                bord.getBord()[i][j][k].getBlok().getKleur().getBlue()};
                        gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, kleur, 0);
                        glut.glutSolidCube(0.9f / scaleFactor);
                        gl.glPopMatrix();
                    }
                }
            }
        }
        gl.glPopMatrix();

    }

    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }
    // Muis luisteraars
    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        prevMouseX = e.getX();
        prevMouseY = e.getY();
        if ((e.getModifiers() & e.BUTTON3_MASK) != 0) {
            mouseRButtonDown = true;
        }
    }

    public void mouseReleased(MouseEvent e) {
        if ((e.getModifiers() & e.BUTTON3_MASK) != 0) {
            mouseRButtonDown = false;
        }
    }

    public void mouseClicked(MouseEvent e) {
        if(e.getButton()==e.BUTTON3)
            bord.toggle();
    }

    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Dimension size = e.getComponent().getSize();

        float thetaY = 360.0f * ((float) (x - prevMouseX) / (float) size.width);
        float thetaX = 360.0f * ((float) (prevMouseY - y) / (float) size.height);

        prevMouseX = x;
        prevMouseY = y;

        view_rotx += thetaX;
        view_roty += thetaY;
    }

    public void mouseMoved(MouseEvent e) {
    }

    //Keybord luisteraars
    public void keyTyped(KeyEvent arg0) {
    }

    public void keyPressed(KeyEvent evt) {
        switch (evt.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                bord.beweegX(-1);
                break;
            case KeyEvent.VK_RIGHT:
                bord.beweegX(1);
                break;
            case KeyEvent.VK_UP:
                bord.toggle();
                break;
            case KeyEvent.VK_DOWN:
                bord.beweegY(1);
                break;
            case KeyEvent.VK_SPACE:
                bord.beweegY(1);
                break;
            case KeyEvent.VK_Q:
                bord.beweegX(-1);
                break;
            case KeyEvent.VK_S:
                bord.beweegX(1);
                break;
            case KeyEvent.VK_D:
                bord.beweegZ(-1);
                break;
            case KeyEvent.VK_F:
                bord.beweegZ(1);
                break;
                
            case KeyEvent.VK_P:
                distance +=1;
                this.repaint();
                break;
            case KeyEvent.VK_M:
                distance -=1;
                this.repaint();
                break;
        }
    }

    public void keyReleased(KeyEvent arg0) {
    }
}

